package com.dlc.felear.xiaoensale.deviceControlSf;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.deviceUtil.Serialhelper;
import com.dlc.felear.xiaoensale.dlc_serial_port.DlcSerialPortClient;
import com.dlc.felear.xiaoensale.entity.Operator;
import com.dlc.felear.xiaoensale.factory.CmdList;
import com.dlc.felear.xiaoensale.helper.JsonHelper;
import com.dlc.felear.xiaoensale.helper.Session;
import com.dlc.felear.xiaoensale.utils.HexUtil;
import com.dlc.felear.xiaoensale.utils.RecordLog;

import org.simple.eventbus.EventBus;

import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class NewDeviceControl implements SensorStatusInfo.SensorStatusCallback {
    private static final String TAG = "NewDeviceControl";
    private static NewDeviceControl deviceControlHelper;
    private ArrayBlockingQueue<Operator> cmds = new ArrayBlockingQueue<>(300);
    private ThreadPoolExecutor scheduledThreadPool;
    private String inputIoSerialName;
    private SensorStatusInfo sensorStatusInfo;
    private TiaoliaoControl tiaoliaoControl;
    private HotControl hotControl;
    private LiaoheControl liaoheControl;
    private GuotiActionControl guotiActionControl;
    private Serialhelper serialhelper;
    private long tempTime = 0;
    private ScheduledExecutorService timers;
    private static volatile HashMap<Integer, Integer> cacheCmds;
    private String type = "M400";

    public static NewDeviceControl getDeviceControlHelper(Context context) {
        if (deviceControlHelper == null) {
            synchronized (NewDeviceControl.class) {
                if (deviceControlHelper == null) {
                    deviceControlHelper = new NewDeviceControl(context);
                }
            }
        }
        return deviceControlHelper;
    }


    /**
     * @param flag f炒菜结束 t炒菜开始
     */
    public void isChaocaiStatus(boolean flag) {
        tiaoliaoControl.isChaocaiStatus(flag);
        guotiActionControl.isChaocaiStatus(flag);
        liaoheControl.isChaocaiStatus(flag);
        hotControl.setCcFlag(flag);
        if (TextUtils.equals(type, "M600") || TextUtils.equals(type, "M260")) {
            hotControl.setAutoJr(false);
        }
        tempTime = System.currentTimeMillis();
    }


    private NewDeviceControl(Context context) {
        try {
            scheduledThreadPool = new ThreadPoolExecutor(4, 15, 60, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>(250));
            timers = new ScheduledThreadPoolExecutor(1);
            serialhelper = Serialhelper.getInstance();
            cacheCmds = new HashMap<>();
            inputIoSerialName = serialhelper.getKzbSerialNo();
            sensorStatusInfo = SensorStatusInfo.getInstance(this, scheduledThreadPool);
            guotiActionControl = GuotiActionControl.getInstance(sensorStatusInfo,inputIoSerialName, scheduledThreadPool);
            tiaoliaoControl = new TiaoliaoControl(inputIoSerialName, guotiActionControl);
            tiaoliaoControl.setDeviceType(Session.getSession().getString("D_GT_TYPE", "M400"));
            hotControl = HotControl.getInstance(serialhelper.getJxSerialNo());
            liaoheControl = new LiaoheControl(cacheCmds, inputIoSerialName, sensorStatusInfo, scheduledThreadPool, guotiActionControl);
            type = Session.getSession().getString("D_GT_TYPE", "M400");
            loopTime();
            startLoop();
        } catch (Exception e) {
            log(e.getMessage(), 0);
        }
    }

    public void setOperatorAutoHandle(OperatorAutoHandle operatorAutoHandle) {
        tiaoliaoControl.setOperatorAutoHandle(operatorAutoHandle);
    }


    /**
     * 轮训读取控制器的状态
     */
    public void loopTime() {
        Session session = Session.getSession();
        int function = session.getInt(Constant.DEVICE_FUNTION, 0);
        if (function != 0) {
            return;
        }
        delayInit();
        timers.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    sendCmd(inputIoSerialName, CmdList.queryIOStatus());
                } catch (Exception e) {
                    log(e.getMessage(), 0);
                }

            }
        }, 2000, 100, TimeUnit.MILLISECONDS);
    }


    private void delayInit() {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    sensorStatusInfo.setIswork();
                    isChaocaiStatus(false);
                } catch (Exception e) {
                    log("delayInit Exception:" + e.getMessage(), 0);
                }
            }
        });
    }


    /**
     * 指令分发队列
     */
    private void startLoop() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Operator data = null;
                    while ((data = cmds.take()) != null) {
                        dispatcherCmd(data);
                        Thread.sleep(20);
                    }
                } catch (Exception e) {
                    startLoop();
                }

            }
        }).start();
    }


    /**
     * 指令分发
     *
     * @param
     */
    public void dispatcherCmd(Operator operator) {
        Log.e(TAG, "分发步骤：" + operator.getName() + " data:" + JsonHelper.toJson(operator));
        Log.e(TAG, "上一个步骤时间间隔：" + (System.currentTimeMillis() - tempTime) / 1000 + " 当前步骤:" + operator.getName());
        tempTime = System.currentTimeMillis();
        switch (operator.getName()) {
            case Constant.ACTION_NAME_TZJR:
            case Constant.ACTION_NAME_KQJR:
                if (operator.getValue() > 0 && operator.getValue1() > 0) {
                    tiaoliaoControl.setChoufengStatus(255);
                }
                hotControl.setLevel(operator.getValue(), operator.getValue1());
                break;
            case Constant.ACTION_NAME_DKGZ:
            case Constant.ACTION_NAME_GSGZ:
                tiaoliaoControl.setChoufengStatus(operator.getValue());
                break;
            case Constant.ACTION_NAME_KSJB:
            case Constant.ACTION_NAME_TZJB:
                guotiActionControl.gtJb(operator.getValue1(), operator.getValue());
                break;
            case Constant.ACTION_NAME_FW:
                fuwei(operator.getValue());
                break;
            case Constant.ACTION_NAME_XG:
                guotiActionControl.actionXg();
                break;
            case Constant.ACTION_NAME_JSC:
                liaoheControl.openGz(operator.getValue(), 20);
                break;
            case Constant.ACTION_NAME_DC:
                guotiActionControl.actionCg();
                break;
            case Constant.ACTION_NAME_CCJD:
                ccPosition(operator.getValue1(), operator.getValue1());
                break;
            case Constant.ACTION_NAME_DS:
                guotiActionControl.setDaoshuiAction();
                break;
            case Constant.ACTION_NAME_Y:
            case Constant.ACTION_NAME_T:
            case Constant.ACTION_NAME_JJ:
            case Constant.ACTION_NAME_YOU:
            case Constant.ACTION_NAME_HHJY:
            case Constant.ACTION_NAME_GQZ:
            case Constant.ACTION_NAME_YTJJ:
            case Constant.ACTION_NAME_LAOCHOU:
            case Constant.ACTION_NAME_HONGYOU:
            case Constant.ACTION_NAME_SHUI:
            case Constant.ACTION_NAME_JLA:
                tiaoliaoControl.setOperator(operator);
                break;
            case Constant.ACTION_NAME_JC:
                guotiActionControl.SDJCposition();
                break;
            case Constant.ACTION_NAME_CCSC:
                guotiActionControl.controlZfRun(operator.getValue());
                break;
            default:
                log("分发步骤 忽略的指令:" + operator.getName(), 0);
                break;
        }
        saveLogToFile("序号：" + operator.getNum() + " 炒菜步骤:" + operator.getName() + " value1:" + operator.getValue() + " value2=" + operator.getValue1());
    }

    private void fuwei(int num) {
//        log("锅体和料盒复位", 0);
        liaoheControl.clearData();
        guotiActionControl.fuWei();
    }

    private int byteToInt(byte value) {
        String hex = Integer.toHexString(value & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        return Integer.parseInt(hex, 16);
    }

    private void ccPosition(int num, int delay) {
        guotiActionControl.setCcLevel(num, delay);
    }


    /**
     * 接受输入状态
     *
     * @param cmd
     */
    public void recieveInputResult(byte[] cmd) {
        if (CmdList.checkDataComplete(cmd) && cmd[1] == (byte) 0x07) {
            sensorStatusInfo.recieveSensorData(cmd);
        }
    }


    public void recieveJrData(byte[] data) {
        hotControl.recievePowerDataNew(data);
    }


    public void recieveCmd(Operator operator) {
        log("缓存的指令:" + JsonHelper.toJson(operator), 0);
        cmds.offer(operator);
    }


    public void recieveTemperatureData(int maxValue, int avgValue, int minValue) {
        hotControl.recieveTemperatureData(maxValue, avgValue, minValue);
    }


    private void sendCmd(String serialNo, byte[] data) {
        DlcSerialPortClient.getInstance().send(serialNo, data);
    }


    private void log(String msg, int flag) {
        if (!TextUtils.isEmpty(msg)) {
            Log.e(TAG, msg);
        }
        if (flag == 1) {
            EventBus.getDefault().post(msg, Constant.DEVICE_ERROR_MSG_SHOW);
        }
    }


    private void sendWarnMsg(int level, String msg) {
        Log.e(TAG, "告警等级=" + level + " msg=" + msg);
    }


    @Override
    public void sensorStatusResultCallback(final int on, final int off) {
        log("sensorStatusResultCallback=" + on, 0);
        guotiActionControl.sensorStatus(on);
        liaoheControl.sensorStatus(on);

    }

    public void openOutPutIo(int index) {
        log("openOutPutIo=" + index, 0);
        sendCmd(inputIoSerialName, CmdList.OpenDO(index, 1));
    }

    public void openOutPutIo(int num, int time) {
        log("DO:" + num + "打开时长:" + time, 0);
        sendCmd(inputIoSerialName, CmdList.OpenDO(num, time));
    }


    /**
     * 单次电机启动
     *
     * @param num  电机编号
     * @param dir  方向
     * @param puls 脉冲数
     */
    public void startSfOnce(int num, int dir, int puls) {
        log("电机单次转：" + HexUtil.bytes2HexString(CmdList.setSfOncePlus(num, dir, puls)), 0);
        sendCmd(inputIoSerialName, CmdList.setSfOncePlus(num, dir, puls));
    }

    /**
     * 电机启动（一直转）
     *
     * @param num  电机编号
     * @param dir  方向
     * @param puls 脉冲数
     */
    public void startSfAlways(int num, int dir, int puls) {
        log("电机一直转：" + HexUtil.bytes2HexString(CmdList.setSfPlus(num, dir, 0)), 0);
        sendCmd(inputIoSerialName, CmdList.setSfPlus(num, dir, 0));
    }

    /**
     * 电机停止
     *
     * @param num  电机控制编号
     * @param flag 是否需要减速
     */
    public void stopSf(int num, int flag) {
        log("电机停止转：" + HexUtil.bytes2HexString(CmdList.setSfStop(num, flag)), 0);
        sendCmd(inputIoSerialName, CmdList.setSfStop(num, flag));
    }

    public void setSfSpeed(int num, int speed) {
        log("设置电机速度：" + HexUtil.bytes2HexString(CmdList.setSfSpeend(num, speed)), 0);
        sendCmd(inputIoSerialName, CmdList.setSfSpeend(num, speed));
    }

    public String getErrorMsg() {
        String temp = liaoheControl.getErrorMsg();
        if (TextUtils.isEmpty(temp)) {
            temp = guotiActionControl.getErrorMsg();
        }
        return temp;
    }

    public void allActionStop() {
        try {
            log("取消所有炒菜", 0);
            isChaocaiStatus(false);
            DlcSerialPortClient.getInstance().clearCmdData();
            hotControl.allStop();
            guotiActionControl.allStop();
            closedAllDo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止全部动作
     */
    private void closedAllDo() {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    hotControl.setLevel(0, 0);
                    Thread.sleep(50);
                    for (int i = 1; i < 31; i++) {
                        sendCmd(inputIoSerialName, CmdList.OpenDO(i, 0));
                        Thread.sleep(50);
                    }
                } catch (Exception e) {

                }
            }
        });
    }

    private void saveLogToFile(String msg) {
        RecordLog.getInstance().saveLog(msg);
    }

}
